#include "main.h"
#include <errno.h>
#include <string.h>

BILLINFO *pBillinfo;//指向小票数据结构的指针
YANINFO *pyaninfo;//指向烟结构体的指针
TEL *ptel; //定义指向电话号码二维数组的指针
size_t quantity = 0; //保存卷烟数据导入时的条码总数
MSG ttyS0_copy; //保存键盘发送过来的信息
MSG ttyS0_verMSG; //保存生成的版本回复信息
MSG ttyS0_initMSG; //保存生成的初始化回复信息
MSG ttyS0_ackMSG; //保存生成的间巡回复信息
MSG USBHIDdat_MSG; //保存usbhid要发送的信息
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
volatile uint16_t KeyPressFlag = 0; //按键按下置1，线程中码牌响应后对其置0
sem_t transferAllowFlag;
sem_t transferStartFlag;
uint8_t *pttyS1RxBuff =NULL;
uint8_t *pttyS0RxBuff =NULL;
uint8_t *pttyUSBRxBuff =NULL;
uint8_t *pttyUSBHIDRxBuff =NULL;

int main(int argc, char *argv[])
{
    //load yan.dat file
    //int filefd = open(FILEYANDAT, O_RDONLY);
    if(argc < 3)
    {
        printf("ERROR: missing parameter!\n");
        exit(1);
    }else if(argc >4)
    {
        printf("ERROR: too much parameter!, only one parameter\n");
        exit(1);
    }
    //打开yan.dat文件
    int filefd = open(argv[1], O_RDONLY);//打开yan.dat文件
    if(filefd == -1)
    {
        printf("open %s file failed!\n", argv[1]);
        printf("Error: %s\n", strerror(errno));
        exit(1);
    }
    struct stat fileInfo;//文件信息结构体
    memset(&fileInfo, 0, sizeof(fileInfo));
    int yanstat = stat(argv[1], &fileInfo);
    if(yanstat !=0)
    {
        printf("Get file stat failed!\n");
        printf("Error: %s\n", strerror(errno));
    }
    int8_t *pfilebuff = (int8_t*)malloc(fileInfo.st_size);//创建内存空间
    if(pfilebuff == NULL)
    {
        printf("Create %s malloc pfileyandatbuff failed!\n", argv[1]);
        printf("Error: %s\n", strerror(errno));
        exit(1);
    }
    memset(pfilebuff, 0, fileInfo.st_size);
    int rflag = read(filefd, pfilebuff, fileInfo.st_size);//读取文件内容
    if(rflag == -1)
    {
        printf("read %s file failed!\n", argv[1]);
        printf("Error: %s\n", strerror(errno));
        exit(1);
    }
    quantity = GetYanFileItem(pfilebuff, fileInfo.st_size); //获取烟数据文本的总条数
    pyaninfo = ConvertFile2Struc(pfilebuff, fileInfo.st_size, quantity); //将导入的文件转为结构体变量
    if(pyaninfo == NULL)
    {
        printf("point pyaninfo has a invalid address, process terminal!\n");
        exit(1);
    }
    // printf("\n********* print yan infomation... *************\n");
    // for(uint16_t ii=0; ii<quantity; ii++) //print load yan.dat file for debug
    // {
    //     printf("SN: %3d  ", ii);
    //     for(uint16_t zz=0; zz<13; zz++)
    //     {
    //        // printf("%02x ", yaninfo[ii].ean13[zz]);
    //        printf("%c", (*(pyaninfo+ii))->ean13[zz]);
    //     }
    //     printf("    ");
    //     for(uint16_t yy=0; yy<7; yy++)
    //     {
    //         printf("%c", (*(pyaninfo+ii))->price[yy]);
    //     }
    //     //printf("\n");
    //  printf("\n");   
    // }
    // printf("########## print terminal! #############\n"); 
    
    printf("load < %s > file success, file size: %ld bytes, total items: %ld\n", argv[1],fileInfo.st_size, quantity);
    free(pfilebuff);
    pfilebuff = NULL; 
    close(filefd);
    
    //load yan.dat file terminal

    //load tel.dat file
    // 打开 TEL.DAT
    int telfilefd = open(argv[2], O_RDONLY); // 打开 TEL.DAT
    if(telfilefd == -1)
    {
        printf("open %s file failed!\n", argv[2]);
        printf("Error: %s\n", strerror(errno));
        exit(1);
    }
    struct stat fileTelInfo;
    memset(&fileTelInfo, 0, sizeof(fileTelInfo));
    int telstat = stat(argv[2], &fileTelInfo);
    if(telstat !=0)
    {
        printf("Get file stat failed!\n");
        printf("Error: %s\n", strerror(errno));
    }
    int8_t *pfileteldatbuff = (int8_t*)malloc(fileTelInfo.st_size);
    if(pfileteldatbuff == NULL)
    {
        printf("Create %s malloc pfileteldatbuff failed!\n", argv[2]);
        printf("Error: %s\n", strerror(errno));
        exit(1);
    }
    int rtelflag = read(telfilefd, pfileteldatbuff, fileTelInfo.st_size);//读取电话号码文件内容
    if(rtelflag == -1)
    {
        printf("read %s file failed!\n", argv[2]);
        printf("Error: %s\n", strerror(errno));
        
        exit(1);
    }
    maxMemberItem = GetMemberItemCount(pfileteldatbuff, fileTelInfo.st_size);
    ptel = GetMemberItemContent(pfileteldatbuff, fileTelInfo.st_size);
    if(ptel == NULL)
    {
        printf("point ptel has a invalid address, process terminal!\n");
        exit(1);
    }
    // for(uint8_t ii=0; ii<maxMemberItem; ii++)
    // {
    //     printf("tel %d: ", ii);
    //     for(uint8_t offset=0; offset<11; offset++)
    //     {
    //         printf("%c", (*(ptel+ii))->tel[offset]);
    //     }
    //     printf("\n");
    // }
    printf("load < %s > file success, file size: %ld bytes, total items: %d\n", argv[2],fileTelInfo.st_size, maxMemberItem);
    free(pfileteldatbuff);
    pfileteldatbuff = NULL;
    close(telfilefd);
    
    OpenUart(UART0, &ttyS0FD);//ttyS0接口接收码牌机过来的数据
    InitUart(ttyS0FD, B9600);
    MSG ttyS0;
    ttyS0.fd = ttyS0FD;
    ttyS0_ackMSG.fd = ttyS0FD;
    ttyS0_verMSG.fd = ttyS0FD;
    ttyS0_initMSG.fd = ttyS0FD;

    OpenUart(UART1, &ttyS1FD);//ttyS1接口接收收银机小票数据
    InitUart(ttyS1FD, B115200);
    MSG ttyS1;
    ttyS1.fd = ttyS1FD;

    OpenUart(UARTUSB, &ttyUSBFD);//ttyUSB接口接收小键盘过来的数据
    InitUart(ttyUSBFD, B9600);
    MSG ttyUSB;
    ttyUSB.fd = ttyUSBFD;

    OpenUart(UART3, &USBHIDFD); //ttyS3,接USBHID模块
    InitUart(USBHIDFD, B9600);
    MSG ttyUSBHID;
    ttyUSBHID.fd = USBHIDFD; //此结构体保存接收数据
    USBHIDdat_MSG.fd = USBHIDFD; //此结构体保存发送数据
    
    memcpy(&ttyS0_copy, &ttyS0, sizeof(MSG)); //复制生成一个ttyS0副本，方便后续发送键盘过来的数据到码牌机

    //创建USB HID模块接收线程， USB HID模块过来的数据
    pttyUSBHIDRxBuff = (uint8_t*)malloc(USBHIDBUFFSIZE);
    if(pttyUSBHIDRxBuff == NULL)
    {
        printf("err: malloc USBHIDBUFFSIZE failed!, process terminaled!\n");
        printf("Error: %s\n", strerror(errno));
        exit(1);
    }
    memset(pttyUSBHIDRxBuff, 0, USBHIDBUFFSIZE);
    if( pthread_create(&USBHIDRxThreadID, NULL, USBHIDRxThreadProcess, &ttyUSBHID) !=0) 
    {
        printf("Create USB HID device  listen thread failed! process terminal!\n");  
        printf("Error: %s\n", strerror(errno));     
        exit(1);
    }
    printf("Create USB HID device listen thread succesfully!\n");
    printf("Reset USB HID module ...\n");
    GenerateUSBHIDResetMsg(&USBHIDdat_MSG); //软件复位USB HID
    USBHIDtransferDat(&USBHIDdat_MSG);
    sleep(2);
    printf("Check USB HID module status ...\n");
    do
    {
        GenerateUSBHIDCmdGetInfoMsg(&USBHIDdat_MSG); //获取USB HID 芯片版本、状态等信息
        USBHIDtransferDat(&USBHIDdat_MSG);
        sleep(1);
        if(ttyUSBHID.buff[6] == 0) printf("USB HID: NOT CONNECT\n");
        if(ttyUSBHID.buff[6] == 1) printf("USB HID: CONNECT OK!\n");

        
    } while (ttyUSBHID.buff[6] == 0);

    //创建ttyS0接收线程,码牌机过来的数据
    pttyS0RxBuff = (uint8_t*)malloc(TTYS0RXBUFFSIZE);
    if(pttyS0RxBuff == NULL)
    {
        printf("err: malloc pttyS0RxBuff failed!, process terminaled!\n");
        printf("Error: %s\n", strerror(errno));
        exit(1);
    }
    memset(pttyS0RxBuff, 0, TTYS0RXBUFFSIZE);
    if( pthread_create(&ttyS0RxThreadID, NULL, TTYS0RxThreadProcess, &ttyS0) !=0) 
    {
        printf("Create MAPAI device listen thread failed, process terminal!\n");       
        exit(1);
    }
    printf("Create MAPAI device listen thread succesfully!\n");

    //创建ttyS1接收线程，收银机过来的数据
    pttyS1RxBuff = (uint8_t*)malloc(TTYS1RXBUFFSIZE);
    if(pttyS1RxBuff == NULL)
    {
        printf("err: malloc pttyS1RxBuff failed!, process terminaled!\n");
        printf("Error: %s\n", strerror(errno));
        exit(1);
    }
    memset(pttyS1RxBuff, 0, TTYS1RXBUFFSIZE);
    pBillinfo = (BILLINFO*)malloc(sizeof(BILLINFO)); //创建pbillinfo，指向收银机过来的小票数据结构
    if(pBillinfo == NULL)
    {
        printf("err: malloc pBillinfo failed!, process terminaled!\n");
        printf("Error: %s\n", strerror(errno));
        exit(1);
    }
    memset(pBillinfo, 0, sizeof(BILLINFO)); //清空空间
    if( pthread_create(&ttyS1RxThreadID, NULL, TTYS1RxThreadProcess, &ttyS1) !=0) 
    {
        printf("Create AOBO device  listen thread failed! process terminal!\n");       
        exit(1);
    }
    printf("Create AOBO device listen thread succesfully!\n");

    //创建ttyusb接收线程，小键盘过来的数据
    pttyUSBRxBuff = (uint8_t*)malloc(TTYUSBRXBUFFSIZE);
    if(pttyUSBRxBuff == NULL)
    {
        printf("err: malloc pttyUSBRxBuff failed!, process terminaled!\n");
        printf("Error: %s\n", strerror(errno));
        exit(1);
    }
    memset(pttyUSBRxBuff, 0, TTYUSBRXBUFFSIZE);
    if( pthread_create(&ttyUSBRxThreadID, NULL, TTYUSBRxThreadProcess, &ttyUSB) !=0) 
    {
        printf("Create KEYBOARD device  listen thread failed! process terminal!\n");       
        exit(1);
    }
    printf("Create KEYBOARD device listen thread succesfully!\n");
    sem_init(&transferAllowFlag, 0, 0); //设置信号量为0，在发送进程中，允许
    sem_init(&transferStartFlag, 0, 0);  //设置传输开始信号量为0，
    if(signal(SIGUSR1, SigProc) == SIG_ERR)
    {
        printf("can not catch SIGUSR1\n");
        exit(1);
    }
    
    signal(SIGINT, SigProc);

    while (1)
    { 
        sleep(1); //延时1秒 ， 不可删除
       
    } //while end
    return 0;    
}

void SigProc(int sig)
{
    if(sig == SIGINT)
    {
        printf("Start clean ... \n");

        printf("Terminaled thread ttyS0RxThreadID ... ");
        if(pthread_cancel(ttyS0RxThreadID) == 0) printf("done!\n");
            else printf("failed\n");
        printf("Terminaled thread ttyS1RxThreadID ... ");
        if(pthread_cancel(ttyS1RxThreadID) == 0) printf("done!\n");
            else printf("failed\n");
        printf("Terminaled thread ttyUSBRxThreadID ... ");
        if(pthread_cancel(ttyUSBRxThreadID) == 0) printf("done!\n");
            else printf("failed\n");
        printf("Terminaled thread USBHIDRxThreadID ... ");
        if(pthread_cancel(USBHIDRxThreadID) == 0) printf("done!\n");
            else printf("failed\n");
        pthread_join(ttyS0RxThreadID, NULL);
        pthread_join(ttyS1RxThreadID, NULL);
        pthread_join(ttyUSBRxThreadID, NULL);
        pthread_join(USBHIDRxThreadID, NULL);

        free(pttyS0RxBuff);
        printf("Clean malloc memory pttyS0RxBuff ... done!\n");
        free(pttyS1RxBuff);
        printf("Clean malloc memory pttyS1RxBuff ... done!\n");
        free(pttyUSBRxBuff);
        printf("Clean malloc memory pttyUSBRxBuff ... done!\n");
        free(pttyUSBHIDRxBuff);
        printf("Clean malloc memory pttyUSBHIDRxBuff ... done!\n");
        free(pyaninfo);
        printf("Clean malloc memory pyaninfo ... done!\n");
        free(ptel);
        printf("Clean malloc memory ptel ... done!\n");
        free(pBillinfo);
        printf("Clean malloc memory pBillinfo ... done!\n");
        printf("All Memory Clean Done!\n");
        printf("Process has exit! bye bye!\n");
        exit(0);
    }  
}
